package com.github.lzm320a99981e.component.dataautomation;

import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Maps;
import org.springframework.util.ReflectionUtils;

import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.Map;

/**
 * 上下文信息
 */
public class DataAutomationContext extends JSONObject {
    /**
     * 本地线程变量，线程内变量共享，线程间不可见
     */
    private final static ThreadLocal<DataAutomationContext> threadLocal = ThreadLocal.withInitial(() -> new DataAutomationContext(Maps.newConcurrentMap()));
    /**
     * 抽取类
     */
    private static final String EXTRACTOR_CLASS_KEY = "extractClass";
    /**
     * 处理类
     */
    private static final String PROCESSOR_CLASS_KEY = "processorClass";
    /**
     * 抽取请求参数
     */
    private static final String EXTRACT_REQUEST_KEY = "extractRequest";
    /**
     * 抽取响应参数
     */
    private static final String EXTRACT_RESPONSE_KEY = "extractResponse";
    /**
     * 处理响应参数
     */
    private static final String PROCESS_RESPONSE_KEY = "processResponse";

    /**
     * 抽取重试失败后进入恢复阶段携带的异常
     */
    private String EXTRACT_RECOVER_EXCEPTION_STACK_TRACE_KEY = "extractRecoverExceptionStackTrace";
    /**
     * 处理重试失败后进入恢复阶段携带的异常
     */
    private String PROCESS_RECOVER_EXCEPTION_STACK_TRACE_KEY = "processRecoverExceptionStackTrace";
    /**
     * 传输重试失败后进入恢复阶段携带的异常
     */
    private String TRANSFER_RECOVER_EXCEPTION_STACK_TRACE_KEY = "transferRecoverExceptionStackTrace";

    /**
     * 处理流程是否终止
     */
    private boolean termination;

    /**
     * 构建上下文对象
     *
     * @param map
     */
    public DataAutomationContext(Map<String, Object> map) {
        super(map);
    }

    /**
     * 获取当前线程的上下文对象
     *
     * @return
     */
    public static DataAutomationContext getCurrentContext() {
        return threadLocal.get();
    }

    public Class getExtractorClass() {
        return (Class) get(EXTRACTOR_CLASS_KEY);
    }

    public void setExtractorClass(Class extractorClass) {
        this.put(EXTRACTOR_CLASS_KEY, extractorClass);
    }

    public Class getProcessorClass() {
        return (Class) get(PROCESSOR_CLASS_KEY);
    }

    public void setProcessorClass(Class processorClass) {
        this.put(PROCESSOR_CLASS_KEY, processorClass);
    }

    public Object getExtractRequest() {
        return this.get(EXTRACT_REQUEST_KEY);
    }

    public void setExtractRequest(Object extractRequest) {
        this.put(EXTRACT_REQUEST_KEY, extractRequest);
    }


    public Object getExtractResponse() {
        return this.get(EXTRACT_RESPONSE_KEY);
    }

    public void setExtractResponse(Object extractResponse) {
        this.put(EXTRACT_RESPONSE_KEY, extractResponse);
    }

    public Object getProcessResponse() {
        return this.get(PROCESS_RESPONSE_KEY);
    }

    public void setProcessResponse(Object processResponse) {
        this.put(PROCESS_RESPONSE_KEY, processResponse);
    }

    public String getExtractRecoverExceptionStackTrace() {
        return getString(EXTRACT_RECOVER_EXCEPTION_STACK_TRACE_KEY);
    }

    public void setExtractRecoverExceptionStackTrace(Exception extractRecoverException) {
        put(EXTRACT_RECOVER_EXCEPTION_STACK_TRACE_KEY, getExceptionStackTrace(extractRecoverException));
    }

    public String getProcessRecoverExceptionStackTrace() {
        return getString(PROCESS_RECOVER_EXCEPTION_STACK_TRACE_KEY);
    }

    public void setProcessRecoverExceptionStackTrace(Exception processRecoverException) {
        put(PROCESS_RECOVER_EXCEPTION_STACK_TRACE_KEY, getExceptionStackTrace(processRecoverException));
    }

    public String getTransferRecoverExceptionStackTrace() {
        return getString(TRANSFER_RECOVER_EXCEPTION_STACK_TRACE_KEY);
    }

    public void setTransferRecoverExceptionStackTrace(Exception transferRecoverException) {
        put(TRANSFER_RECOVER_EXCEPTION_STACK_TRACE_KEY, getExceptionStackTrace(transferRecoverException));
    }

    public boolean isTermination() {
        return termination;
    }

    public void setTermination(boolean termination) {
        this.termination = termination;
    }

    /**
     * 获取异常的堆栈信息
     *
     * @param e
     * @return
     */
    public static String getExceptionStackTrace(Exception e) {
        StringWriter out = new StringWriter();
        PrintWriter pw = new PrintWriter(out);
        try {
            e.printStackTrace(pw);
            return out.toString();
        } catch (Exception ex) {
            ReflectionUtils.rethrowRuntimeException(ex);
        } finally {
            pw.close();
        }
        return null;
    }
}
